<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!-- 
        数据劫持是vue的一个核心, 另一个核心是组件化, 由于vue对数据进行劫持, 当数据发生改变的时候用户可以及时在页面上看到响应数据(MVVM模式)

        对于object类型, 主要的劫持是对这个对象属性的读取和设置操作, 是通过  Object.defineProperty 进行操作

        Object.defineProperty(obj, prop, descriptor)
        obj参数
            定义属性的对象

        prop参数
            定义属性对象需要修改或者是定义的属性名称

        descriptor参数
            定义或修改的属性

            value       该属性的值 (默认undefined)
            writable    为false的时候, 该属性不可修改 (默认true)
            get         读取器 (getter)
            set         设置器 (setter)
     -->
    <p>msg的数据: </p>
    <input type="text" id="inp">
    <script>
        let p = document.querySelector("p");
        let inp = document.getElementById("inp");

        // 需要定义一个对象 (需要劫持的对象)
        let data = {
            msg: "默认值"
        };
        // 模版初始化
        template(data.msg);

        // 执行数据劫持函数
        observer(data, 'msg', "默认值");
        // 数据劫持函数
        function observer(obj, key, value) {
            // 观察属性的变化和设置操作
            Object.defineProperty(obj, key, {
                // 读取器 (读取属性的时候会自动触发)
                get() {
                    console.log("get");
                    // 默认返回的是undefined, 这里需要返回这个属性的值
                    return value;
                },
                // 设置器 (设置属性的时候会自动触发)
                set(newValue) {
                    // newValue参数, 当前设置的新值
                    console.log("set");
                    // 将设置的新值赋值到value属性值上
                    value = newValue;
                    // 模版函数
                    template(newValue);
                }
            })
        };
        // 模版函数
        function template(newValue) {
            p.innerHTML = "msg的数据: " + newValue;
            inp.value = newValue;
        }

        inp.addEventListener("input", (e) => {
            data.msg = e.target.value;
        })
    </script>

















    <script>
        // const object1 = {};

        // Object.defineProperty(object1, 'property1', {
        //     value: 42,
        //     writable: false
        // });

        // object1.property1 = 77;

        // console.log(object1.property1); // 42
    </script>
</body>

</html>